package com.gr.staffpm.pages.login;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;

import com.gr.staffpm.login.model.SimpleUser;
import com.gr.staffpm.pages.behaviour.FocusOnLoadBehavior;

/**
 * The class <code>LoginForm</code> is a subclass of the Wicket
 * {@link Form} class that attempts to authenticate the login request using
 * Wicket auth (which again delegates to Spring Security).
 * @author Graham Rhodes
 * @date   6 Nov 2010
 */
public class LoginForm extends Form<SimpleUser> {

    private static final long serialVersionUID = 1L;
    private TextField<String> username;
    private PasswordTextField password;
    private CheckBox rememberMe;

    public LoginForm(String id, SimpleUser user) {
        super(id, new CompoundPropertyModel<SimpleUser>(user));
        add(new FeedbackPanel("feedback"));
        username = (TextField<String>) new TextField<String>("username").setRequired(true);
        password = new PasswordTextField("password").setResetPassword(true);
        username.add(new FocusOnLoadBehavior());
        add(username);
        add(password);
        // MarkupContainer row for remember me checkbox
        final WebMarkupContainer rememberMeRow = new WebMarkupContainer("rememberMeRow");
        add(rememberMeRow);

        // Add rememberMe checkbox
        rememberMeRow.add(rememberMe = new CheckBox("rememberMe"));
    }

    /**
     * Called upon form submit. Attempts to authenticate the user.
     */
    @Override
    protected void onSubmit() {
        if (login(getUsername(), getPassword(), getRememberMe())) {
            onSignInSucceeded();
        }
        setRedirect(true);
    }

    public String getUsername() {
        return username.getValue();
    }


    public String getPassword() {
        return password.getValue();
    }

    public boolean getRememberMe() {
        return Boolean.valueOf(rememberMe.getValue());
    }

    public void setUsername(TextField<String> username) {
        this.username = username;
    }

    public void setPassword(PasswordTextField password) {
        this.password = password;
    }

    public void setRememberMe(CheckBox rememberMe) {
        this.rememberMe = rememberMe;
    }

    public boolean login(String username, String password, boolean rememberMe) {
        Subject currentUser = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
        try {
            currentUser.login(token);
            return true;

            // the following exceptions are just a few you can catch and handle accordingly. See the
            // AuthenticationException JavaDoc and its subclasses for more.
        } catch (IncorrectCredentialsException ice) {
            error("Password is incorrect.");
        } catch (UnknownAccountException uae) {
            error("There is no account with that username.");
        } catch (AuthenticationException ae) {
            error(ae.getMessage());
        } catch (Exception ex) {
            error("Login failed");
        }
        return false;
    }

    protected void onSignInSucceeded() {
        // If login has been called because the user was not yet
        // logged in, than continue to the original destination,
        // otherwise to the Home page
        if (!continueToOriginalDestination()) {
            setResponsePage(getApplication().getSessionSettings().getPageFactory().newPage(getApplication().getHomePage()));
        }
    }

}
